let W = null;
class Watcher {
  constructor(data, key) {
    this.data = data;
    this.key = key;
    W = this;
    this.get();
    W = null;
  }
  get() {
    return this.data[this.key];
  }
  updata() {
    console.log(
      `${
        this.key
      }的数据发生更新了,我们重新获取一下吧${this.get()},并重新渲染一下视图`
    );
  }
}

class Dep {
  constructor() {
    this.subs = [];
  }
  addDeppend(watcher) {
    this.subs.push(watcher);
  }
  notify() {
    this.subs.forEach((watcher) => {
      watcher.updata();
    });
  }
}

function defineReactive(_data, key, value) {
  observe(value);

  const dep = new Dep();

  Object.defineProperty(data, key, {
    get: function ReactiveGetter() {
      console.log("在数据劫持的getter中获取数据", key);
      if (W) {
        dep.addDeppend(W);
      }
      return value;
    },
    set: function ReactiveSetter(newVal) {
      console.log("在数据劫持的Setter中收到了设置数据", key);
      value = newVal;
      dep.notify();
    },
  });
}

class Observer {
  constructor(_data) {
    this._data = _data;
    if (Array.inArray(this._data)) {
      this.observerArray(this._data);
    } else {
      this.walk(this._data);
    }
  }
  observerArray(_data) {
    _data.foEach((item = observe(item)));
  }

  walk(_data) {
    for (let key of Object.keys(_data)) {
      defineReactive(_data, key, _data[key]);
    }
  }
}

function onserver(_data) {
  if (typeof _data !== "object" || _data === null) return;
  new Observer(_data);
}

function Vue(options) {
  this._data = options.data;

  for (let key in Object.keys(this._data)) {
    Object.defineProperty(this, key, {
      get: function proxyGetter() {
        return this._data[key];
      },
      set: function proxySetter(newVal) {
        this._data[key] = newVal;
      },
    });
  }
  Observer(this._data);
}

const vm = new Vue({
  data: {
    count: 1,
    student: {
      name: "laowang",
      age: 18,
    },
    food: [
      { id: "001", type: "热干面" },
      { id: "002", type: "烧饼" },
    ],
  },
});

function huoqu() {
  new Watcher(vm.food[0], "type");
}

huoqu();

function shezhi() {
  vm.food[0].type = "焖面";
}
shezhi();
